package com.example.mobiledatapackage.controller;

import com.example.mobiledatapackage.domain.Package;
import com.example.mobiledatapackage.exception.BusinessException;
import com.example.mobiledatapackage.exception.BusinessExceptionType;
import com.example.mobiledatapackage.exception.RuleFileCannotFoundError;
import com.example.mobiledatapackage.request.PkgDescText;
import com.example.mobiledatapackage.request.SaveModelReq;
import com.example.mobiledatapackage.response.OnePkgExtractResult;
import com.example.mobiledatapackage.response.SerializeModelResult;
import com.example.mobiledatapackage.service.RegexParseService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.apache.jena.base.Sys;
import org.apache.jena.rdf.model.InfModel;
import org.apache.jena.riot.Lang;
import org.apache.jena.riot.RDFDataMgr;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.BufferedReader;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;


@RestController
@RequestMapping("/admin")
@Slf4j
@Tag(name = "AdminController", description = "管理员操作")
public class AdminController {

    @Autowired
    private InfModel infModel;

    @Autowired
    ResourceLoader resourceLoader;  // 用于读取 /resources 下的文件

    @Autowired
    RegexParseService regexParseService;  // 提供正则解析服务

    /**
     * 将 YAML 配置文件中的应用程序名称注入进来
     */
    @Value("${spring.application.name}")
    private String APP_NAME;

    private static final DateTimeFormatter datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss");

    @PostMapping("/save-model")
    @Operation(summary = "将 RDF 数据序列化到文件中")
    public SerializeModelResult saveRdfModel(@RequestBody @Valid SaveModelReq saveModelReq) {
        // 填写序列化 RDF 路径的默认 path
        // TODO: 默认路径还未写得很好，现在还是个糊弄事的路径
        if (saveModelReq.getPath() == null) {
            String defaultPath = "\\" + APP_NAME + '+' + LocalDateTime.now().format(datetimeFormatter) + ".ttl";
            saveModelReq.setPath(defaultPath);
        }
        // 打开文件并进行序列化
        try {
            // TODO: 检查文件和目录是否处理特殊情况
            FileOutputStream out = new FileOutputStream(saveModelReq.getPath());
            RDFDataMgr.write(out, infModel.getRawModel(), toRdfLang(saveModelReq.getFormat()));
            out.close();
        } catch (IOException e) {
            throw new BusinessException(BusinessExceptionType.RdfSerializeException, e.getMessage());
        }
        return new SerializeModelResult(saveModelReq.getPath(), true);
    }

    @GetMapping("/rules")
    @Operation(summary = "读取推理规则的文件")
    public String getReasonerRules() throws RuleFileCannotFoundError {
        // 获取规则文件
        var resource = new ClassPathResource("\\rule\\recommendRule-dev.rules");
        StringBuilder sb = new StringBuilder();
        try (
                BufferedReader ruleFileReader = new BufferedReader(new InputStreamReader(resource.getInputStream()))
                ) {
            String line;
            while ((line = ruleFileReader.readLine()) != null){
                sb.append(line);
                sb.append("\n");
            }
        } catch (IOException e) {
            throw new RuleFileCannotFoundError();
        }
        return sb.toString();
    }

    @PostMapping("/pkg-extraction")
    @Operation(summary = "根据一段文本，将套餐数据提取出来")
    public List<OnePkgExtractResult> extractPackage(@RequestBody @Valid PkgDescText pkgDescText) {
        System.out.println(pkgDescText);
        List<OnePkgExtractResult> result = new ArrayList<>();
        OnePkgExtractResult o = new OnePkgExtractResult();
        o.setRawText("xxxx");
        o.setPkg(new Package());
        result.add(o);
        return result;
    }

    /**
     * 将字符串表示的RDF序列化类型转化成 Jena 库中的 Lang 类型
     * @param lang 字符串表示的RDF序列化类型
     * @return 相应的 Jena 库中的 Lang 类型
     */
    private Lang toRdfLang(String lang) {
        Lang t;
        switch (lang.toUpperCase(Locale.ROOT)) {
            case "XML":     t = Lang.RDFXML;    break;
            case "NT":      t = Lang.NT;        break;
            case "TTL":     t = Lang.TTL;       break;
            default:        t = Lang.TURTLE;    break;
        }
        return t;
    }

}
